<?php

namespace App\Console\Server;

use Illuminate\Contracts\Container\Container;
use Illuminate\Console\Scheduling\Schedule as BaseSchedule;

class Schedule extends BaseSchedule
{
    /**
     * The Laravel application instance.
     *
     * @var \Illuminate\Contracts\Container\Container
     */
    protected $laravel;

    // 秒级定时任务
    protected $tickEvents = [];

    /**
     * Create a new schedule instance.
     * @param  \Illuminate\Contracts\Container\Container  $laravel
     * @return void
     */
    public function __construct(Container $laravel)
    {
        $this->laravel = $laravel;
        parent::__construct();
    }

    /**
     * Add a new command event to the schedule.
     *
     * @param  string  $command
     * @param  array  $parameters
     * @return \App\Console\Server\Event
     */
    public function exec($command, array $parameters = [])
    {
        if (count($parameters)) {
            $command .= ' ' . $this->compileParameters($parameters);
        }

        $this->events[] = $event = new Event($this->eventMutex, $command);

        return $event;
    }

    public function parseTickEvents()
    {
        $tmp = [];
        foreach ($this->events as $e) {
            if ($e->isTickCmd) {
                $this->tickEvents[] = $e;
            } else {
                $tmp[] = $e;
            }
        }
        $this->events = $tmp;
    }

    /**
     * 获取秒级定时任务
     * 
     * @return \App\Console\Server\Event[]
     */
    public function getTickEvents()
    {
        return $this->tickEvents;
    }

    /**
     * 获取crontab定时任务
     * 
     * @return \App\Console\Server\Event[]
     */
    public function getSchedule()
    {
        $commands = [];
        foreach ($this->dueEvents($this->laravel) as $event) {
            if (!$event->filtersPass($this->laravel)) {
                continue;
            }

            if ($event->onOneServer) {
                $this->runSingleServerEvent($event, $commands);
            } else {
                $this->runEvent($event, $commands);
            }
        }
        return $commands;
    }

    /**
     * Run the given single server event.
     *
     * @param  \Illuminate\Console\Scheduling\Event  $event
     * @return void
     */
    protected function runSingleServerEvent($event, &$commands)
    {
        if ($this->serverShouldRun($event, Carbon::now())) {
            $this->runEvent($event, $commands);
        }
    }

    /**
     * Run the given event.
     *
     * @param  \Illuminate\Console\Scheduling\Event  $event
     * @return void
     */
    protected function runEvent($event, &$commands)
    {
        if ($event->withoutOverlapping &&
            !$event->mutex->create($event)) {
            return;
        }

        $commands[] = $event;
    }
}
